#include<iostream>
#include<string>
#include<regex>
#include<assert.h>

//正则表达式,一种字符串匹配模式，用来检查一个字符串是否包含某种子串，将匹配的子串替换或者从某个子串中取出符合某个条件的子串
//正则表达式的使用并不会提高效率，是的解析HTTP请求的工作变得简单
// bool std::regex_match (const std::string& src , std::smatch& matches , std::regex & e)
//第一个参数为原始字符串，第二个参数为会将提取到的数据存放在matches类似数组的容器中，第三个参数为正则表达式；其返回值会返回提取是否成功

// int main()
// {
//     std::string s = "/number/1234";
//     //创建正则表达式，获取字符串中的数字部分
//     std::regex e("/number/(\\d+)");//()会提取括号中的数据出来，\\d+ 从开始字符开始后一个或多个的字符，并且在匹配的过程中将其提取出来
//     std::smatch matches;

//     bool ret = std::regex_match(s , matches , e);
//     //判断返回值
//     if(ret == false)
//     {
//         return -1;
//     }
//     //遍历matches ，将数据打印出来
//     for(auto & str: matches)
//     {
//         std::cout <<  str << std::endl;
//     }
//     return 0;
// }
//使用正则表达式获取HTTO请求行的解析
// int main()
// {
//     std::string str = "GET /zjx/helloworld/login?user=qin&pass=123456 HTTP/1.1\r\n";
//     // std::string str = "GET /zjx/helloworld/login HTTP/1.1\r\n";
//     //创建保存提取信息出来的数组
//     std::smatch matches;
//     //请求方法的匹配,请求方法有GET POST HEAD PUT DELETE ，使用 | 
//     // std::regex e("(GET | POST | PUT | HEAD | DELETE).*"); //后面的. 表示匹配除了换行符之外的任何单个字符，* 表示匹配前面的子表达式0次或者多次
//     // std::regex e("(GET|POST|PUT|DELETE|HEAD) ([^?]*).*");//^ 表示匹配输入字符串的开始位置，[^?]表示匹配非?字符,带个*表示匹配0次或者多次,没有带* 就只会提取一个字符
//     // std::regex e("(GET|POST|PUT|HEAD|DELETE) ([^?]*)\\?(.*) .*"); // \\?表示原始的？字符，(.*)表示提取? 之后的任意字符一次或者多次，直到遇到空格 
//     std::regex e("(GET|POST|HEAD|DELETD|PUT) ([^?]*)(?://?(.*))? (HTTP/1\\.[01])(?:\n|\r\n)?");
//     //(HTTP/1\\.[01]) 表示在HTTP/1. 的后面有0或1字符 
//     //(?: )? 表示，?:表示匹配某种个数的字符串，但是不匹配； 后面的? 表示匹配前面的表达式一次或者0次
//     bool ret = std::regex_match(str , matches , e);
//     if(ret == false)
//     {
//         return -1;
//     }
//     //遍历打印matches 当中的数据
//     for(auto &s : matches)
//     {
//         std::cout << s << std::endl;
//     }
//     return 0;
// }

//通用类型any 的实现
//由于一个连接必须拥有一个请求接受与解析上下文，因为应用层的协议有许多，所以需要有一个容器能够保存不同类型的数据
//倘若单纯实现为模版，需要指定类型并且指定了类型之后并不能存储其他类型的数据，这是非常局限的；利用多态，存储父类的指针，父类指向子类
//子类为模版类，在其中存储数据
class Any
{
private:
    //父类
    class holder
    {
    public:
        //虚函数
        virtual ~holder(){}
        //获取子类当中存储数据的类型
        virtual const std::type_info& type() = 0;
        //针对子类对象构造出一个新的子类对象 clone,返回父类指针
        virtual holder* clone() = 0;
    };

    //子类
    template<typename T>
    class placeholder : public holder
    {
    public:
        T _val;//存储数据
    public:
        placeholder(const T& val):_val(val)
        {}
        const std::type_info& type() override
        {
            return typeid(T);
        }
        holder* clone() override
        {
            return new placeholder(_val);
        }
        ~placeholder(){}
    };

    //存储数据
    holder* _content;
private:
    Any& Swap(Any& other)//返回值为Any& 是为了支持连续交换
    {
        std::swap(_content , other._content);
        return *this;
    }
public:
    Any():_content(nullptr)
    {}
    //有可能其他类型的数据直接来构造
    //实现一个模版类型的构造
    template<class T>
    Any(const T& content)
    {   
        _content = new placeholder<T>(content);
    }
    //拷贝构造函数
    Any(const Any& other)
    {
        //判断其中是否有数据，没有数据就不拷贝
        if(other._content == nullptr) 
        {
            _content = nullptr;
            return;
        }
        _content = other._content->clone();//基类指针调用子列当中的方法
    }
    //赋值重载，同样实现两个版本
    //利用拷贝构造，现代方法来实现
    Any& operator=( Any other)
    {
        Swap(other);
        return *this;
    }
    template<class T>
    Any& operator=(const T& val)
    {
        //将val 构造成一个Any对象，然后再交换
        Any(val).Swap(*this);
        return *this;
    }
    ~Any()
    {
        //释放资源
        delete _content;
    }
    //获取数据，提供一个get函数,由于数据的类型是多种多样的，所以需要用到函数模版
    template<class T>
    T* get()
    {
        //首先需要确保获取的数据与返回的数据类型一致
        assert(typeid(T) == _content->type());
        return &((placeholder<T>*)_content)->_val;
    }
};

class Test
{
public:
    Test(){std::cout << "构造" << std::endl;}
    Test(const Test& t) 
    {
        std::cout << "拷贝构造" << std::endl;
    }
    ~Test()
    {
        std::cout <<"析构" << std::endl;
    }
};

int main()
{
    Any a;
    a = 10;
    int * p1 = a.get<int>();
    std::cout << *p1 << std::endl;

    a = std::string("hello");
    std::string* p2 = a.get<std::string>();
    std::cout << *p2 << std::endl;
    
    // Test t;
    // a =t;

    a = Test();
    return 0;
}
